﻿using Libs;
using Libs.Egucha;
using System.Diagnostics;

namespace WriteForFighting.Game.Entity
{
    abstract class EntityBase
    {
        public const int InfinityHealth = int.MinValue;

        public double X { get; set; }
        public double Y { get; set; }
        private double _collisionCircleX;
        public double CollisionCircleX { get { return _collisionCircleX; } set { _collisionCircleX = value; } }
        private double _collisionCircleY;
        public double CollisionCircleY { get { return _collisionCircleY; } set { _collisionCircleY = value; } }
        public double CollisionCircleRadius { get; set; }
        private double angle;
        public double Angle
        {
            get { return angle; }
            set
            {
                if (value < 0)
                {
                    angle = (Helper.PI * 2) - value % (Helper.PI * 2);
                }
                else if (Helper.PI * 2 < angle)
                {
                    angle = value % (Helper.PI * 2);
                }
                else
                {
                    angle = value;
                }
            }
        }
        public int MaxHealth { get; set; }
        public int Health { get; set; }
        public bool IsDeath { get; set; }
        public bool IsOverableField { get; set; }
        public Vector vector = new Vector();

        protected double CollisionBoxRelativeX { get; set; }
        protected double CollisionBoxRelativeY { get; set; }
        protected int Age { get; private set; }

#if DEBUG
        private static int colorCollisionCircle = DX.GetColor(255, 0, 255);
#endif

        public EntityBase(double par1X, double par2Y, double par3Angle)
        {
            X = par1X;
            Y = par2Y;
            Angle = par3Angle;
            MaxHealth = InfinityHealth;
            Health = InfinityHealth;
        }

        public void Update(int par1GameTickCount, EntityManager par2PlayersManager,
            EntityManager par3BulletsManager, EntityManager par4EffectsManager)
        {
            if ((Health != InfinityHealth) &&
                (Health <= 0))
            {
                OnDeath(par1GameTickCount, par2PlayersManager, par3BulletsManager, par4EffectsManager);
                IsDeath = true;
                return;
            }

            OnUpdate(par1GameTickCount, par2PlayersManager, par3BulletsManager, par4EffectsManager);

            if (IsOverableField)
            {
                X += vector.x;
                Y += vector.y;
            }
            else
            {
                double nColliX;
                double nColliY;
                GetCollisionCirclePos(out nColliX, out nColliY);
                nColliX += vector.x;
                nColliY += vector.y;

                if ((nColliX - CollisionCircleRadius) < 0)
                {
                    Vector tempv = new Vector(CollisionBoxRelativeX, CollisionBoxRelativeY);
                    tempv.RotateVector(Angle);
                    X = CollisionCircleRadius - tempv.x;
                }
                else if (600 < (nColliX + CollisionCircleRadius))
                {
                    Vector tempv = new Vector(CollisionBoxRelativeX, CollisionBoxRelativeY);
                    tempv.RotateVector(Angle);
                    X = 600 - CollisionCircleRadius - tempv.x;
                }
                else
                {
                    X += vector.x;
                }

                if ((nColliY - CollisionCircleRadius) < 0)
                {
                    Vector tempv = new Vector(CollisionBoxRelativeX, CollisionBoxRelativeY);
                    tempv.RotateVector(Angle);
                    Y = CollisionCircleRadius - tempv.y;
                }
                else if (600 < (nColliY + CollisionCircleRadius))
                {
                    Vector tempv = new Vector(CollisionBoxRelativeX, CollisionBoxRelativeY);
                    tempv.RotateVector(Angle);
                    Y = 600 - CollisionCircleRadius - tempv.y;
                }
                else
                {
                    Y += vector.y;
                }
            }

            GetCollisionCirclePos(out _collisionCircleX, out _collisionCircleY);

            Age++;
        }

        public void Draw(int par1GameTickCount)
        {
            OnDraw(par1GameTickCount);

#if DEBUG
            DrawDataForDebug();
#endif
        }

        public bool GetIsHitEntity(EntityBase par1Entity)
        {
            return !par1Entity.IsDeath &&
                   Collision.GetIsHitCircleAndCircle(new Circle(new PointD(X, Y), CollisionCircleRadius),
                                                     new Circle(new PointD(par1Entity.X, par1Entity.Y), par1Entity.CollisionCircleRadius));
        }

        protected abstract void OnUpdate(int par1GameTickCount, EntityManager par2PlayersManager,
            EntityManager par3BulletsManager, EntityManager par4EffectsManager);

        protected abstract void OnDraw(int par1GameTickCount);

        protected virtual void OnDeath(int par1GameTickCount, EntityManager par2PlayersManager,
            EntityManager par3BulletsManager, EntityManager par4EffectsManager) { }

        private void GetCollisionCirclePos(out double x, out double y)
        {
            Vector tempv = new Vector(CollisionBoxRelativeX, CollisionBoxRelativeY);
            tempv.RotateVector(Angle);
            x = X + tempv.x;
            y = Y + tempv.y;
        }

#if DEBUG
        private void DrawDataForDebug()
        {
            DX.SetDrawBlendMode(DX.DX_BLENDMODE_ALPHA, 200);
            DX.DrawCircle((int)CollisionCircleX, (int)CollisionCircleY,
                (int)CollisionCircleRadius, colorCollisionCircle, DX.FALSE);
            DX.SetDrawBlendMode(DX.DX_BLENDMODE_NOBLEND, 255);
        }
#endif
    }
}
